/*
	gvTooltip 1.0
	
	This sript will hide the default tooltip on Google Visualizations
	and will display a customizalble tooltip.
	
	The script as been tested for Bar, Column, Line, Pie, and Area charts.
	
	
	@author Kevin Jantzer, Folium Parters, LLC
	@date 2010-12-01
	@modified 2010-12-05
	
	@dependencies
		- jQuery
		- gvTooltip CSS
		
		
	USE
	1. Include jQuery and the gvTooltip.js and gvTooltip.css files.
	
	2. Add this after your GV.draw declaration:
		
		gvTooltip("gv_div","data_var",chart_var,"options");
	
			Example:
			gvTooltip("chart_div","data",chart,"{maxWidth: '200px', style: 'clean'}");

	
	3. Add your tooltip text to your "Formatted Data". The formatted data must be in the following format:
	
		<span>Regular Title<div id="gvTooltipData">The data/text that will show up in the tooltip</div></span>
		
		
		
	OPTIONS - gvTooltip supports a few options.
	@maxWidth 		- string 	- limit how wide the tool tip can get. This could be globally defined in the CSS file.
	@offsetLeft 	- int 		- shift the tooltip to the left (-) or the right (+)
	@offsetBottom 	- int		- shfit the tooltip up (+) and down (-)
	@followMouse	- boolean	- whether the tooltip should follow the mouse
	@style			- string	- class to be applied to tooltip for styling
	@position		- string	- where the tooltip should be relative to the mouse
	
	
	
	@todo - add support for the table view
	@todo - better functionality when tooltip overflows a screen side
	
*/

// Default settings
var gvTooltip_defaultSettings = {
	maxWidth		: '300px',
	offsetLeft		: 0,
	offsetBottom	: 0,
	followMouse		: false,
	position		: 'topRight',
	style			: ''
}


// *********************************************************************************************************
// *********************************************************************************************************
// Change code below at your own risk
// *********************************************************************************************************
// *********************************************************************************************************

var gvTooltip_isIE = document.all?true:false;
if (!gvTooltip_isIE) document.captureEvents(Event.MOUSEMOVE)

var gvTooltip_mouseX = 0;	// position of mouse on x axis
var gvTooltip_mouseY = 0;	// position of mouse on y axis
var gvTooltip_elemOver = ''; // element directly beneath the mouse

var gvTooltip_winHeight;
var gvTooltip_iframe;
var gvTooltip_iframeName;
var gvTooltip_iframeLeft;
var gvTooltip_iframeTop;
var gvTooltip_divName;
var gvTooltip_objName = new Array();
var gvTooltip_tooltip;
var gvTooltip_followMouse = 0;
var gvTooltip_bottom;
var gvTooltip_left;
var gvTooltip_settings = gvTooltip_defaultSettings;



/*
	gvTooltip Get Coordinates
	
	this fn is responsible for continually updating
	where the mouse is, and what element is directly 
	beneath it.
*/
function gvTooltipGetCoordinates(e) {

	/*
		Get Mouse Coordiates
	*/
	// IE
	if (gvTooltip_isIE) {
		gvTooltip_mouseX = event.clientX + document.body.scrollLeft;
		gvTooltip_mouseY = event.clientY + document.body.scrollTop;
	
	// other browser, FF,Saf,Chrome.
	}else{
		gvTooltip_mouseX = e.pageX;
		gvTooltip_mouseY = e.pageY;
	}  
	
	// make sure the X,Y coord do not fall under 0
	if (gvTooltip_mouseX < 0){gvTooltip_mouseX = 0;}
	if (gvTooltip_mouseY < 0){gvTooltip_mouseY = 0;}  
	
	
	/*
		Get Element Mouse is Over
	*/
	// IE
	if (e.srcElement){
		gvTooltip_elemOver = e.srcElement;
	
	// other browsers
	}else{ //if (e.target)
		gvTooltip_elemOver = e.target;
	}
	
	if(gvTooltip_settings.followMouse){
		
	}
	
	
	return true;
}


function gvTooltipMouseHandle(e){

	gvTooltipGetCoordinates(e);
	
	/*
	if(gvTooltip_settings.followMouse){
		gvTooltip_bottom = gvTooltip_winHeight - gvTooltip_mouseY + 15;				// CSS: bottom of tooltip
		gvTooltip_left = gvTooltip_mouseX - 20;	// CSS: left of tooltip
		
		gvTooltipReposition(gvTooltip_tooltip,gvTooltip_left,gvTooltip_bottom);
	}
	*/
	
	return true;
}

function gvTooltipMouseHandle_iframe(e){

	gvTooltipGetCoordinates(e);


	if(gvTooltip_settings.followMouse){
		gvTooltip_bottom = gvTooltip_winHeight - (gvTooltip_mouseY + gvTooltip_iframeTop) + 15;				// CSS: bottom of tooltip
		gvTooltip_left = gvTooltip_mouseX + gvTooltip_iframeLeft - 20;	// CSS: left of tooltip
		
		gvTooltipReposition(gvTooltip_tooltip,gvTooltip_left,gvTooltip_bottom);
	}
	
	return true;
}



function gvTooltipSetup(name, options){
	gvTooltip_settings.followMouse = false;
	
	// if options are detected, merge them with the default settings
	if ( options ) { 
		$.extend( gvTooltip_settings, options );
	}
	
	// set the GV div name (where the chart is drawn)
	gvTooltip_divName = name;
	
	// get a hold of the gvTooltip_iframe that contains the drawn chart
	gvTooltip_iframe = document.getElementById(gvTooltip_divName).firstChild
	
	// store gvTooltip_iframe properties
	gvTooltip_iframeName = gvTooltip_iframe.name;
	gvTooltip_iframeLeft = gvTooltip_iframe.offsetLeft;
	gvTooltip_iframeTop = gvTooltip_iframe.offsetTop;
	
	// bind gvTooltipGetCoordinates_iframe to the gvTooltip_iframe window.
	// we do this so that our mouse coordinates are monitored even when hovering over the gvTooltip_iframe. 
	window.frames[gvTooltip_iframeName].document.onmousemove = gvTooltipMouseHandle_iframe;
	document.onmousemove = gvTooltipMouseHandle;
	
	// hide the default GV Tooltip with some simple CSS
	// this was figured out by observeing the DOM created by GV
	window.frames[gvTooltip_iframeName].document.getElementById('chart').firstChild.nextSibling.nextSibling.style.display = 'none';
	
	// window height (used to set gvTooltip_bottom)
	gvTooltip_winHeight = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight;

}



/*
	gvTooltip Show Chart
	
	this fn is called by 
*/
function gvTooltipShowChart(e){

	// update the position of the current iframe
	// we do this because there could be more than one GV on a page
	gvTooltip_iframeLeft = gvTooltip_iframe.offsetLeft;
	gvTooltip_iframeTop = gvTooltip_iframe.offsetTop;
	
	
	//**************** Set the gvTooltip Position ****************
	/*
		1.) Default gvTooltip position: Where ever the mouse is when first beginning to hover over the element
	*/
	gvTooltip_bottom = gvTooltip_winHeight - (gvTooltip_mouseY + gvTooltip_iframeTop) + 15;				// CSS: bottom of tooltip
	gvTooltip_left = gvTooltip_mouseX + gvTooltip_iframeLeft - 20;	// CSS: left of tooltip

	
	/*
		2.) Circle Element - such as on the Line Chart
	*/
	if(gvTooltip_elemOver.nodeName == 'circle'){
		
		// we find the position (distance from top and left) of the circle element
		circleTop = parseFloat( (gvTooltip_elemOver.getAttribute('cy')) );
		circleLeft = parseFloat( (gvTooltip_elemOver.getAttribute('cx')) );
		
		// we re-calculate the gvTooltip position
		gvTooltip_bottom = gvTooltip_winHeight - ( circleTop + gvTooltip_iframeTop ) + 20;
		gvTooltip_left = circleLeft + gvTooltip_iframeLeft - 20;
	}
	
	
	/*
		3.) Rectangle Element - such as on a Bar or Column Chart
	*/
	if(gvTooltip_elemOver.nodeName == 'rect'){
		
		// we find the position (distance from top and left) of the rectangle element
		rectTop = parseFloat( (gvTooltip_elemOver.getAttribute('y')) );
		rectLeft = parseFloat( (gvTooltip_elemOver.getAttribute('x')) );
		rectWidth = parseFloat( (gvTooltip_elemOver.getAttribute('width')) );
	
		// we re-calculate the gvTooltip position
		gvTooltip_bottom = gvTooltip_winHeight - ( rectTop + gvTooltip_iframeTop ) + 11;
		gvTooltip_left = rectLeft + gvTooltip_iframeLeft + rectWidth - 30;
	}
	
	
	// adjust tooltip position with custom settings
	gvTooltip_bottom = gvTooltip_bottom + gvTooltip_settings.offsetBottom;
	gvTooltip_left = gvTooltip_left + gvTooltip_settings.offsetLeft;
	
	
	//**************** Set the gvTooltip Data/Text ****************
	
	// we use the Formatted data from our GV data table
	var tooltip_data = eval(gvTooltip_objName[gvTooltip_divName]+'.getFormattedValue(e.row,e.column)');
	tooltip_data = $(tooltip_data).find('#gvTooltipData').html();
	
	
	// create the inline css style for the tooltip
	var gvTooltipStyle = 'left: '+gvTooltip_left+'px; bottom: '+gvTooltip_bottom+'px;';
	gvTooltipStyle += 'max-width:'+gvTooltip_settings.maxWidth+';';
	
	var gvTooltipClass = gvTooltip_settings.style;
	
	// display the tooltip
	gvTooltip_tooltip = $('<div id="gvTooltip" class="'+gvTooltipClass+'" style="'+gvTooltipStyle+'">'+
		tooltip_data+
		'<div class="arrow"></div></div>');
	
	
	// show the tooltip
	gvTooltip_tooltip.appendTo('#'+gvTooltip_divName);
	
	gvTooltipGetCoordinates(e);
	gvTooltipReposition(gvTooltip_tooltip);
	
}


/*
	gvTooltip Reposition
	
	this fn re-positions the tooltip based on 
	the settings. Default is 
*/
function gvTooltipReposition(gvTooltip_tooltip,specLeft,specBottom){
	
	
	var gvTooltip_tooltip_height = gvTooltip_tooltip.height();
	var gvTooltip_tooltip_width = gvTooltip_tooltip.width();
	var gvTooltip_tooltip_position = gvTooltip_tooltip.offset();
	var gvTooltip_tooltip_left	= gvTooltip_tooltip_position.left;
	var gvTooltip_tooltip_top	= gvTooltip_tooltip_position.top;
	var gvTooltip_tooltip_bottom = gvTooltipTrimPX(gvTooltip_tooltip.css('bottom'));
	
	// newLeft is given if followMouse is set to true
	if(gvTooltip_settings.followMouse){
		gvTooltip_tooltip_left = specLeft;
		gvTooltip_tooltip_bottom = specBottom;
	}
	
	//alert(gvTooltip_tooltip_bottom);
	
	switch(gvTooltip_settings.position){
		
		case 'topLeft':
			
			var newLeft = (gvTooltip_tooltip_left) - gvTooltip_tooltip_width + 23;
			var newBottom = gvTooltip_tooltip_bottom;
			
			gvTooltip_tooltip.css('left',newLeft+'px').css('bottom',newBottom);
			gvTooltip_tooltip.find('.arrow').css('left',(gvTooltip_tooltip_width-14)+'px');
			
			break;
			
			
		case 'topMiddle':
			
			var newLeft = (gvTooltip_tooltip_left - (gvTooltip_tooltip_width/2)) + 15;
			var newBottom = gvTooltip_tooltip_bottom;
			
			gvTooltip_tooltip.css('left',newLeft+'px').css('bottom',newBottom+'px');
			gvTooltip_tooltip.find('.arrow').css('left',((gvTooltip_tooltip_width/2)-5)+'px');
		
			break;
			
			
		case 'rightMiddle':
		
			var newLeft = gvTooltip_tooltip_left + 40;
			var newBottom = (gvTooltip_tooltip_bottom - 25) - (gvTooltip_tooltip_height/2);
			
			gvTooltip_tooltip.css('left',newLeft+'px').css('bottom',newBottom+'px');
			gvTooltip_tooltip.addClass('left');
			gvTooltip_tooltip.find('.arrow').css('bottom',(gvTooltip_tooltip_height/2 - 5)+'px');
		
			break;
			
			
		case 'rightBottom':
		
			var newLeft = gvTooltip_tooltip_left + 40;
			var newBottom = (gvTooltip_tooltip_bottom - 25) - (gvTooltip_tooltip_height-10);
			
			gvTooltip_tooltip.css('left',newLeft+'px').css('bottom',newBottom+'px');
			gvTooltip_tooltip.addClass('left');
			gvTooltip_tooltip.find('.arrow').css('bottom',(gvTooltip_tooltip_height - 15)+'px');
		
			break;
			
		case 'rightTop':
		
			var newLeft = gvTooltip_tooltip_left + 40;
			var newBottom = (gvTooltip_tooltip_bottom - 25) - 15;
			
			gvTooltip_tooltip.css('left',newLeft+'px').css('bottom',newBottom+'px');
			gvTooltip_tooltip.addClass('left');
		
			break;
			
		case 'leftMiddle':
		
			var newLeft = gvTooltip_tooltip_left - (gvTooltip_tooltip_width + 15);
			var newBottom = (gvTooltip_tooltip_bottom - 25) - (gvTooltip_tooltip_height/2);
			
			gvTooltip_tooltip.css('left',newLeft+'px').css('bottom',newBottom+'px');
			gvTooltip_tooltip.addClass('right');
			gvTooltip_tooltip.find('.arrow').css('bottom',(gvTooltip_tooltip_height/2 - 5)+'px');
			gvTooltip_tooltip.find('.arrow').css('left',(gvTooltip_tooltip_width + 11)+'px');
		
			break;
			
			
		case 'leftBottom':
		
			var newLeft = gvTooltip_tooltip_left - (gvTooltip_tooltip_width + 15);
			var newBottom = (gvTooltip_tooltip_bottom - 25) - (gvTooltip_tooltip_height-10);
			
			gvTooltip_tooltip.css('left',newLeft+'px').css('bottom',newBottom+'px');
			gvTooltip_tooltip.addClass('right');
			gvTooltip_tooltip.find('.arrow').css('bottom',(gvTooltip_tooltip_height - 15)+'px');
			gvTooltip_tooltip.find('.arrow').css('left',(gvTooltip_tooltip_width + 11)+'px');
		
			break;
			
		case 'leftTop':
		
			var newLeft = gvTooltip_tooltip_left - (gvTooltip_tooltip_width + 15);
			var newBottom = (gvTooltip_tooltip_bottom - 25) - 15;
			
			gvTooltip_tooltip.css('left',newLeft+'px').css('bottom',newBottom+'px');
			gvTooltip_tooltip.addClass('right');
			gvTooltip_tooltip.find('.arrow').css('left',(gvTooltip_tooltip_width + 11)+'px');
		
			break;
		
		case 'bottomRight':
			
			//var newLeft = (gvTooltip_tooltip_left) - gvTooltip_tooltip_width + 23;
			var newBottom = (gvTooltip_tooltip_bottom - 60) - (gvTooltip_tooltip_height-10);
			
			gvTooltip_tooltip.css('bottom',newBottom+'px');
			gvTooltip_tooltip.addClass('top');
			gvTooltip_tooltip.find('.arrow').css('bottom',(gvTooltip_tooltip_height+11)+'px');
			
			break;
			
		case 'bottomLeft':
			
			var newLeft = (gvTooltip_tooltip_left) - gvTooltip_tooltip_width + 23;
			var newBottom = (gvTooltip_tooltip_bottom - 60) - (gvTooltip_tooltip_height-10);
			
			gvTooltip_tooltip.css('bottom',newBottom+'px').css('left',newLeft+'px');
			gvTooltip_tooltip.addClass('top');
			gvTooltip_tooltip.find('.arrow')
				.css('bottom',(gvTooltip_tooltip_height+11)+'px')
				.css('left',(gvTooltip_tooltip_width-14)+'px');
			
			break;
			
		case 'bottomMiddle':
			
			var newLeft = (gvTooltip_tooltip_left - (gvTooltip_tooltip_width/2)) + 15;
			var newBottom = (gvTooltip_tooltip_bottom - 60) - (gvTooltip_tooltip_height-10);
			
			gvTooltip_tooltip.css('bottom',newBottom+'px').css('left',newLeft+'px');
			gvTooltip_tooltip.addClass('top');
			gvTooltip_tooltip.find('.arrow')
				.css('bottom',(gvTooltip_tooltip_height+11)+'px')
				.css('left',((gvTooltip_tooltip_width/2)-5)+'px');
		
			break;

		// topRight	
		default:
			gvTooltip_tooltip.css('left',specLeft+'px');
			gvTooltip_tooltip.css('bottom',specBottom+'px');
		
			break;
	}

	
	return true;
}



/*
	gvTooltip Remove
	
	this fn removes the current tooltip.
*/
function gvTooltipRemove(e){
	gvTooltip_followMouse = 0;
	//alert('should have removed1');
	$('#gvTooltip').remove();
	//alert('should have removed2');
}



/*
	gvTooltip Init.
*/
function gvTooltip(name,objName,obj,options){

	/*
		Remove Default Only
		
		if the objName = removeDefaultOnly, then we are not
		going to bind gvTooltip, we're just going to remove (hide)
		the default GV tooltip
	*/
	if(objName === 'removeDefaultOnly'){
		gvTooltip_iframeName = document.getElementById(name).firstChild.name;
		window.frames[gvTooltip_iframeName].document.getElementById('chart').firstChild.nextSibling.nextSibling.style.display = 'none';	
	
	/*
		Initiate gvTooltip
	*/
	}else{
		gvTooltip_objName[name] = objName;
	
		gvSetupFn = "gvTooltipSetup('"+name+"',"+options+")";
		document.getElementById(name).setAttribute("onmouseover",gvSetupFn)
	    google.visualization.events.addListener(obj, 'onmouseout', gvTooltipRemove);
		google.visualization.events.addListener(obj, 'onmouseover', gvTooltipShowChart);
	}
}


function gvTooltipTrimPX(value){
  return value.substr(0,value.length-2);
}
